<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>饼图</title>
        <style>
            .container {
                margin: 30px auto;
                width: 600px;
                height: 300px;
                border: 1px solid #000;
            }
            polyline {
                fill: none;
                stroke: #000000;
                stroke-width: 2px;
                stroke-dasharray: 5px;
            }
        </style>
    </head>
    <body>
        <div class="container">
            <svg width="100%" height="100%"></svg>
        </div>
        <script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
        <script>
            window.onload = function() {
                var width = 600, height = 300;
                // 创建一个分组用来组合要画的图表元素
                var main = d3.select('.container svg').append('g')
                        .classed('main', true)
                        .attr('transform', "translate(" + width/2 + ',' + height/2 + ')');
                // 模拟数据
                var dataset = [
                    {name: '购物', value: 983},
                    {name: '日常饮食', value: 300},
                    {name: '医药', value: 1400},
                    {name: '交通', value: 402},
                    {name: '杂费', value: 134}
                ];
                // 转换原始数据为能用于绘图的数据
                var pie = d3.layout.pie()
                        .sort(null)
                        .value(function(d) {
                            return d.value;
                        });
                // pie是一个函数
                var pieData = pie(dataset);
                // 创建计算弧形路径的函数
                var radius = 100;
                var arc = d3.svg.arc()
                        .innerRadius(0)
                        .outerRadius(radius);
                var outerArc = d3.svg.arc()
                        .innerRadius(1.2 * radius)
                        .outerRadius(1.2 * radius);
                var oArc = d3.svg.arc()
                        .innerRadius(1.1 * radius)
                        .outerRadius(1.1 * radius);
                var slices = main.append('g').attr('class', 'slices');
                var lines = main.append('g').attr('class', 'lines');
                var labels = main.append('g').attr('class', 'labels');
                // 添加弧形元素（g中的path）
                var arcs = slices.selectAll('g')
                        .data(pieData)
                        .enter()
                        .append('path')
                        .attr('fill', function(d, i) {
                            return getColor(i);
                        })
                        .attr('d', function(d){
                            return arc(d);
                        });
                // 添加文字标签
                var texts = labels.selectAll('text')
                        .data(pieData)
                        .enter()
                        .append('text')
                        .attr('dy', '0.35em')
                        .attr('fill', function(d, i) {
                            return getColor(i);
                        })
                        .text(function(d, i) {
                            return d.data.name;
                        })
                        .style('text-anchor', function(d, i) {
                            return midAngel(d)<Math.PI ? 'start' : 'end';
                        })
                        .attr('transform', function(d, i) {
                            // 找出外弧形的中心点
                            var pos = outerArc.centroid(d);
                            // 改变文字标识的x坐标
                            pos[0] = radius * (midAngel(d)<Math.PI ? 1.5 : -1.5);

                            return 'translate(' + pos + ')';
                        })
                        .style('opacity', 1);

                var polylines = lines.selectAll('polyline')
                        .data(pieData)
                        .enter()
                        .append('polyline')
                        .attr('points', function(d) {
                            return [arc.centroid(d), arc.centroid(d), arc.centroid(d)];
                        })
                        .attr('points', function(d) {
                            var pos = outerArc.centroid(d);
                            pos[0] = radius * (midAngel(d)<Math.PI ? 1.5 : -1.5);
                            return [oArc.centroid(d), outerArc.centroid(d), pos];
                        })
                        .style('opacity', 0.5);
            };
            function midAngel(d) {
                return d.startAngle + (d.endAngle - d.startAngle)/2;
            }
            function getColor(idx) {
                var palette = [
                    '#2ec7c9', '#b6a2de', '#5ab1ef', '#ffb980', '#d87a80',
                    '#8d98b3', '#e5cf0d', '#97b552', '#95706d', '#dc69aa',
                    '#07a2a4', '#9a7fd1', '#588dd5', '#f5994e', '#c05050',
                    '#59678c', '#c9ab00', '#7eb00a', '#6f5553', '#c14089'
                ]
                return palette[idx % palette.length];
            }
        </script>
    </body>
</html>